package org.mwielocha.jxcube.tasks;

import static org.mwielocha.jxcube.db.Database.clear;
import static org.mwielocha.jxcube.db.Database.insertQuery;
import static org.mwielocha.jxcube.db.Database.lookupAllQuery;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.cmc.music.metadata.IMusicMetadata;
import org.cmc.music.metadata.MusicMetadataSet;
import org.cmc.music.myid3.MyID3;
import org.farng.mp3.TagException;
import org.mwielocha.jxcube.db.Database;
import org.mwielocha.jxcube.ut.Utilities;

public class PopulateDatabaseTask extends AbstractTask {

  protected String directoryRoot;
  
  protected Database db;
  
  protected AudioFileFilter audioFileFilter = new AudioFileFilter();
  
  public PopulateDatabaseTask(String directoryRoot) {
    this.directoryRoot = directoryRoot;
  }

  @Override
  public void runTask() {
    
    try {
      
      db = new Database();
        
      db.open();
      
      if(!isRunning()) {
        return;
      }
      
      db.executeDML(clear());
      
      Stack<File> stack = new Stack<File>();
      
      ResultSet rs = db.executeSQL(lookupAllQuery("synch"));
      
      while(rs.next()) {
        stack.push(new File(rs.getString(1)));
      }
     
      File root = null;
      
      while(!stack.isEmpty() && getStatus() == TaskStatus.RUNNING) {
        
        root = stack.pop();
        
        System.out.println("entering directory " + root.getName());
        
        for(File file : root.listFiles(audioFileFilter)) {
          
          if(file.isDirectory()) {
            stack.push(file);
          } else {
            insertFileToDatabase(file);
          }
        }
      }
      
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
    
  protected void insertFileToDatabase(File f) throws SQLException, TagException, IOException, ClassNotFoundException {
    
    Map<String, Object> values = new HashMap<String, Object>();
    
    if(db.count(f.getCanonicalPath()) > 0) {
      return;
    }
    
    try {
    
//      MP3File mp3 = new MP3File(f);
//
//      if(mp3.hasID3v2Tag()) {
//        values.put("album", mp3.getID3v2Tag().getAlbumTitle());
//        values.put("title", mp3.getID3v2Tag().getSongTitle());
//        values.put("track", mp3.getID3v2Tag().getTrackNumberOnAlbum());
//        values.put("artist", mp3.getID3v2Tag().getAuthorComposer());
//        values.put("genre", mp3.getID3v2Tag().getSongGenre());
//      } else if(mp3.hasID3v1Tag()) {
//        values.put("album", mp3.getID3v1Tag().getAlbumTitle());
//        values.put("title", mp3.getID3v1Tag().getSongTitle());
//        values.put("artist", mp3.getID3v1Tag().getArtist());
//        values.put("genre", mp3.getID3v1Tag().getSongGenre());
//      } 
      
      MusicMetadataSet src_set = new MyID3().read(f); // read metadata

      if (src_set != null) {
          
        IMusicMetadata metadata = src_set.getSimplified();
        
        values.put("album", metadata.getAlbum());
        values.put("title", metadata.getSongTitle());
        values.put("track", metadata.getTrackNumberFormatted());
        values.put("artist", metadata.getArtist());
        values.put("genre", metadata.getGenreName());
        Number duration = metadata.getDurationSeconds();
        if(duration != null) {
          values.put("time", Utilities.formatSeconds(duration.intValue()));
        }
      }  
      
    } catch (Exception e) {
      e.printStackTrace();
    }
    
    if(values.get("title") == null || ((String) values.get("title")).trim().length() == 0) {
      values.put("title", f.getName());
    }
    
    values.put("path", f.getCanonicalPath());
    
 //   System.out.println(f.getName());
 //   System.out.println(values);
    
    db.executeDML(insertQuery(values));
  }
  
  @Override
  public void cleanUp() {
    try {
     db.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  class AudioFileFilter implements FileFilter {
    
    protected static final String REGEX 
      = ".*[.MP3]";
    
    @Override
    public boolean accept(File f) {
      return f.getName().toUpperCase().endsWith(".MP3") || 
      f.getName().toUpperCase().endsWith(".FLAC") ||
      f.getName().toUpperCase().endsWith(".APE") || f.isDirectory();
    }
  }
}
